package com.cskaoyan.javase.oop3._0abstract._0introduction;

import javafx.animation.Animation;

/**
 * 抽象类的引入
 * 以下猫狗继承案例，是一个非常基础的继承语法的代码。
 * 思考一下Animal类的继承体系，有什么问题吗？
 *
 * 从以下两个角度分析：
 *      1.从代码角度上，有没有冗余代码？
 *      2.从设计角度上，在这个案例中，会存在一个Animal类的对象吗？
 *
 * 分析一下
 * 单纯从代码角度上，有没有冗余代码？
 * 实际上是有的。从方法调用的角度考虑，Animal类当中的shout方法从来没有被调用过。该方法单纯就是让子类继承并重写的，它实际上没有被调用的需求。从最理想的角度上来说，它的方法体是可以去掉的，仅保留一个声明让子类去重写就可以了。
 * 当然代码多几行少几行并不重要，重要是：从设计角度出发，Animal类是一个抽象的概念，用于指代所有动物。程序中根本不需要创建它的对象。而且对于一个抽象的概念，也不应该、也不可能去描述它的行为。
 *
 *      综上，我们提出两个改进的方向：
 *      1.Animal类是一个抽象概念,就是作为顶层抽象祖先类而存在的,它的作用就是被继承,所以它不需要创建对象
 *              那干脆这个类就不要创建对象了.
 *      2.Animal类当中的shout方法不需要方法体，仅用于作为被继承和重写一个方法声明。
 *
 * 新的语法:
 *      1.如何在类中声明定义抽象方法?
 *         语法: [访问权限修饰符] abstracts 返回值类型 方法名(形参列表);
 *         注意: 抽象方法不需要实现,它不需要方法体,不可以加大括号.
 *
 *      2.抽象类中才有抽象方法,普通类没有抽象方法.
 *          抽象类的定义:
 *          [访问权限修饰符] abstracts class 类名{
 *              //  类体
 *          }
 *
 * 综上,Animal类成为了抽象类,抽象类不能创建对象
 * 抽象类中还有抽象方法,抽象方法没有方法体,它的目的就是为了被继承和重写
 *
 * 抽象类仍然是一个类,是一个特殊的类
 * Animal在案例中,仍然是一个父类
 * 它仍然有两个子类: Cat,Dog
 * 除了不能创建抽象类的对象以外,其他的正常使用
 * 包括多态现象仍然存在
 *
 * shout方法现在是一个抽象方法,它没有方法体,它定义的目的就是为了被继承和重写
 * 所以在子类中可以给出该方法的实现
 * 就是方法的重写.
 *
 * @since 16:11
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 'Animal' is abstracts; cannot be instantiated
        // new Animal();

        Animal a;
        a = new Cat();
        a.shout();
        a = new Dog();
        a.shout();
    }
}

abstract class Animal {
    /*
        1,直接去掉大括号号会报错: '{' or ';' expected 所以加上分号
        2,Missing method body, or declare abstracts 成员方法必须有方法体,除非它是一个声明为抽象的抽象方法
        3.将方法直接声明为抽象方法后,又报错了,信息是:
            Abstract method in non-abstracts class 抽象方法必须处在抽象类中
            Class 'Animal' must either be declared abstracts or implement abstracts method 'shout()' in 'Animal'
                一个普通类中是没有抽象方法的,除非是一个抽象类,抽象类中才有抽象方法.
      */
    public abstract void shout();
}

class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("猫叫");
    }
}

class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}